Connection Configuration (CCNF Resource ID 200) 14
Client Side Line-level (CLLN Resource ID 200) 15
Actions 16
kSecurityStartup 16
kSecurityShutdown 16
kSecurityBegin 16
kSecurityEnd 16
kSecurityDataAvailable 16
kSecurityAbort 16
kSecurityTickleAction 17
ARA Service Routines 18
ARARead 19
ARAWrite 21
ARALogMessage 22
ARACallBackAt 23
ARAAllowUser 24
ARADontAllowUser 25
ARAReadSecurityData 26
ARAReadLockSecurityData 27
ARAWriteSecurityData 28
ARAUnlockSecurityData 29
ARAGetUserInfo 30
ARATickleMe 31
ARACompleteOperation 32
Appendix A: Security Interface Header File 33
Appendix B: Security Module Shell 41
Appendix C: Miscellaneous 48
Runtime Environment 48
Building an Add-on Security Module 48
ARA Security Interface Disk 49
Introduction
This document describes the add-on security interface used in Apple Remote Access (ARA). This document is written for a security module writer, and explains the ARA interface as seen from an add-on security module.
Add-on security modules (security modules) contain code resources that allow additional methods of authenticating users. ARA uses passwords and a call-back mechanism as its default security. If you have a system for identifying a user, you can develop a security module to integrate your authentication methods into ARA.
We have defined two types of security devices. Devices that sit in front of or behind a modem and physically prevent a connection prior to user authentication are called line-level security devices. Systems that perform their authentication after the ARA server and its client have established a connection are classified as protocol-level security devices. You can develop security modules for each type of device.
The next section gives a brief overview of add-on security modules.
The Security Module Structure section describes a module and its structure in more detail.
The Code Resources section describes the different kinds of code resources that can exist in a security module.
The Actions section describes the actions ARA sends to code resources to request services.
The ARA Service Routines section describes the services that ARA provides to security modules.
Appendix A is the header file for gaining access to ARA Service Routines.
Appendix B is an empty shell for building a code resource.
Appendix C contains miscellaneous information about security module's such as a modules runtime environment, how you can build a module, and the enclosed developer disk contents.
Overview
A security module is a Macintosh file type 'CLMP'. The creator is vendor specific. You can request a creator for your security module from Apple Developer Technical Support (DTS).
Internally a security module contains a number of special resources. Every module must contain an information resource that describes your modules capabilities. Additionally your module may contain a number of code resources. These code resources are executed to perform various functions (e.g. authentication, configuration) for your security module. ARA then can use your module to authenticate a user's identity beyond the password mechanism that it contains. ARA security modules that are placed in the Extensions folder.
The following diagram illustrates the contents of a security module:
The information resource is described in the module Information Resource section.
Each of the code resources provides an entry point. This is a routine which will be called when ARA needs to execute a code resource. The entry point routine and the operations it must support are described in the Code Resource Structure section.
When a code resource is loaded, it will be able to access ARA to request certain services. For example it can have data sent to the remote machine. These services are provided as routines that can be called from a security module. They are described in the ARA Service Routines section.
The following diagram is a high level view of a loaded code resource:
Security Module Structure
A security module is built by creating a Macintosh file that has a 'CLMP' type. This is used by ARA to identify the file as a security module. The module has to be placed in the Extensions folder for ARA to find it. You can do this by dragging it on top of your system folder after installing ARA. The module's creator is defined by you. You must request a creator from Developer Technical Support (DTS).
Additionally the file must contain at least a 'sinf' resource, and a number of code resources for performing various operations. The 'sinf' resource and the code resources are described below.
Currently there are five types of code resources that ARA supports. They are described in sub-sections below.
Code resources must have the appropriate type, and their resource ID should be 200.
Module Information Resource ('sinf' ID 200)
Your module must have a 'sinf' resource with a resource ID of 200. The 'sinf' resource describes what the module's capabilities are.
In your resource definition file, you should create a 'sinf' resource, and fill in the appropriate fields. The template for the resource is defined in a file named "SecurityTypes.r". This file is found on the developer disk. The following is the template for a 'sinf' resource:
type 'sinf' { /* security information resource */
unsigned longint; /* fflags contains info about module */
The first longint is a set of flags that define what the capabilities of the module are. The values for the flags are defined in "SecurityResInfo.h", found on the developer disk. The values should be a combination of the following using the "OR" operator:
kSecurityHasLineLevel Use this flag if your module is to be used for line-level authentication of a user. This flag causes the module to be displayed on the client side. It let's the user select this module for a connection document, used to connect to a port with a physical security device.
kSecurityHasProtocolLevel
This flag indicates the module provides protocol level authentication. It can be used in combination with the kSecurityHasServerSide and kSecurityHasClientSide flags to indicate if the module supports the client side, server side, or both.
kSecurityHasServerSide
This flag is set for a module that provides the code resources needed for the server side. Any module that has code to be executed on the server should set this flag, including user configuration.
kSecurityHasClientSide
This flag is set for a module that provides code resources needed for the client side. Any module that has code to be executed on the client should set this flag.
kSecurityHasUserConfig
This flag is used for a protocol-level module that has a code resource for configuring users on the server. Has 'UCNF' resource.
kSecurityHasConnectionConfig
This flag is used for a line-level module that has a code resource for security configuration on the client side. Has a 'CCNF' resource.
kSecurityHasUserDialog Don't use this flag.
kSecurityHasConnectionDialog Don't use this flag.
The second longint is the signature of the module. This value uniquely identifies your security module. You should reserve a value through Apple Developer Technical Support (DTS). This value should be the same as your file's creator, but it can be different. When they are different, ARA uses the value defined in the 'sinf' resource. For protocol-level modules this signature is used to associate a client module with the server module.
The next three longints are version numbers and are only used for protocol level modules. The first field is "fversion" and defines the module's version. The field after "fversion" are "fmin_version", and "fmax_version". For protocol-level authentication, they are used for checking the client module's compatibility with the server's. The client's "fversion" must be a number between the server module's "fmin_version" and "fmax_version".
The next two longints, "fserver_data" and "fclient_data", are not used, and should be set to zero.
The last field is a Pascal string that is your module's name. This name is used in dialog boxes and anywhere your modul'es name is displayed.
Code Resource Structure
The following sub-sections describe the structure of code resources.
MySecurityProcEntry
Every code resource must provide a routine named "MySecurityProcEntry". This is the entry point to the code resource. ARA calls it through the Security Interface. It should be defined as follows:
pascal long MySecurityProcEntry( SecurityActions Action,
SecurityReference MyReference,
long LongParam )
ARA sends actions to your code resources to request it to perform a service. You should process the actions and return control to ARA as quickly as possible. Actions are defined in the file SecurityPublic.h. The "Actions" section describes actions in detail. The following is a list of the actions:
kSecurityStartup
kSecurityShutdown
kSecurityBegin
kSecurityEnd
kSecurityDataAvailable,
kSecurityAbort
kSecurityTickleAction
MyReference is a unique value that defines an instance of the code resource. It is used when you call any of the ARA Service Routines. It uniquely identifies your thread.
LongParam is used to pass additional information for an action. Currently it is only used with kSecurityTickleAction.
Your entry routine should process the action as soon as possible. It should not stay go into any loops. It can post asynchronous calls to ARA and other Toolbox routines, but it should return control back to ARA quickly. YOU MUST RETURN CONTROL BACK TO ARA AS SOON AS POSSIBLE.
Your routine's return value is a result code ARA examines for possible errors in "MySecurityProcEntry". The possible result codes are "SecurityErrors" defined in "SecurityPublic.h". Return "kSecurityNoErr" if your routine is successful.
SecurityInterface.o
"SecurityInterface.o" is the glue file that provides the ARA Service Routines. It must be linked with each code resource. When linking a code resource, you must have "SecurityInterface.o" as the first file in the linker's object file list. The MPW linker does not shuffle code. The entry point to "SecurityInterface.o" must become the entry point to your code resource.
MPW linker uses the -m option to perform code-flow analysis and remove any dead code. To keep your executable code from being stripped, you must provide the following option in the linker command line:
-m SECURITYINTERFACEENTRYPROC
Completion Routine
Most of the ARA Service Routines are asynchronous. After an asynch ARA routine finishes, it informs you code resource by calling a completion routine. Your completion routine should have the following declaration:
You pass a pointer to your completion routine as one of the parameters to asynchronous ARA Service Routines.
MyReference should is the same value passed to "MySecurityProcEntry". It identifies your instance.
ResultCode is the result of the asynchronous ARA Service you had requested. It will be non zero if the operation failed. It will contain one of the values in ARAErr defined in SecurityPublic.h. You should check its value at the start of your completion routine before you do any other processing. If a read or write times out, the ResultCode will be ARATimeout.
DataPtr is the pointer you passed to the asynch ARA Service Routine. E.g. this will point to the data read by ARARead.
DataSize will be the actual size of processed data. E.g. the number of bytes read by ARARead.
CompletionParam is an additional long you provide. Its value will be the same value you passed to the asynch ARA Service Routine. You can use it as a state indicator. E.g. you can define an enumeration containing the set of all your states. When you call an asynch ARA routine, pass the state you want to be in when the call is done. E.g. pass "kFinished1stRead" to ARARead. When your completion routine gets called with CompletionParam equal to "kFinished1stRead", the ARARead has finished and you can go to the next state. See the sample module on the developer disk for an example of this.
You should not call any Memory Manager routines, or any routines that result in a Memory Manager call from a completion routine. If you need to call these types of routines, call ARATickleMe and handle it in the kSecurityTickleAction.
Runtime Environment (A5 World)
An A5 World is setup for your code resource by ARA. You don't need to be concerned with initializing or setting up the A5 world in the code resource. ARA sets up the A5 world prior to executing any of the code resource (entry routine, and completion routines). Since the code resource has an A5 world, it you can have static (global) data and use the data the same way as an application.
During the execution of your code resource, the resource fork of the security module is open, and it is put on top of the resource forks stack. The file is opened in read only mode, so you should not attempt to write any data to the module's resource fork. A better way of storing data is to store it in a separate preference file, which will not be deleted when you update a user's security module.
You can make calls to Mac Toolbox routines. Whenever possible you should call asynchronous routines, so you can return control to ARA. Furthermore, you should not go into any loops or call SystemTask as a way of returning control to ARA.
ARA Service Routines
ARA provides a number of services accessible through ARA Service Routines. The header file "SecurityInterface.h" has the declarations for these routines. To use them you must link with "SecurityInterface.o".
The ARA Service Routines are described in detail in a later section.
User Configuration (UCNF Resource ID 200)
This code resource is executed when a user window is open on the ARA server admin, and the security module's configuration button is selected. It is used for configuring protocol-level security information on a per-user basis. The code resource should display a modal dialog box and get any needed information. It can store 150 bytes of data for each user (see ARAWriteSecurityData, and ARAReadSecurityData).
On kSecurityBegin you should start your processing, e.g. request to read the existing security data (ARAReadLockSecurityData), or to get the user's name (ARAGetUserInfo). When you've obtained this information, you can call ARATickleMe to put up the modal dialog box (it must be a modal dialog box). You must display the user's name at the top of this dialog box. The user can then input/modify the information and either save or cancel. If the user selects to save the data, you must write it out by calling ARAWriteSecurityData. This information will then be available to the server-side protocol-level authentication module.
The following ARA Service Routines can be used by a UCNF code resource:
ARALogMessage
ARAReadSecurityData
ARAReadLockSecurityData
ARAUnlockSecurityData
ARAWriteSecurityData
ARAGetUserInfo
ARATickleMe
ARACompleteOperation
Client-side Protocol (CLPR Resource ID 200)
This code resource is executed on the ARA client for protocol-level authentication. The corresponding server-side protocol-level module is also executed on the server, and the two module's can communicate with each other.
The client module's state should be driven by the server, and when the authentication has been completed, both sides should call ARAAllowUser/ARADontAllowUser, so ARA can progress to the next state.
A CLPR module can pass a maximum of 500 bytes of data to ARAWrite/ARARead. The ARAWrite and ARARead will communicate with the server-side protocol (i.e. ARARead on the client side will read data written by the server module).
On kSecurityBegin you should start your state machine, getting information from the user and sending it to the server module. The server module should inform the client module when the user is authenticated or rejected, at which time it should call ARAAllowUser, or ARADontAllowUser.
The following ARA Service Routines can be used by a CLPR code resource:
ARARead
ARAWrite
ARALogMessage
ARAAllowUser
ARADontAllowUser
ARATickleMe
ARACompleteOperation
Server-side Protocol (SRPR Resource ID 200)
This code resource is executed on the server to authenticate a user after the ARA protocol has been established. It can communicated with the corresponding client authentication module. ARA loads the client module automatically.
This code resource should get the user information from the client module and determine if the user should be allowed in. Once a user has been authenticated or rejected, this code resource should inform the client side, and then call ARAAllowUser/ARADontAllowUser. The client code resource should also call ARAAllowUser/ARADontAllowUser.
A SRPR code resource can write and read a maximum of 500 bytes of data using ARAWrite or ARARead. The data is exchanged with client module.
This code resource can use ARAReadLockSecurityData, ARAReadSecurityData, ARAWriteSecurityData, and ARAUnlockSecurityData to access and modify the 150 bytes of security data associated with each user. Each security module can have 150 bytes of data for each user.
The following ARA Service Routines can be used by a SRPR code resource:
ARARead
ARAWrite
ARALogMessage
ARACallBackAt
ARAAllowUser
ARADontAllowUser
ARAReadSecurityData
ARAReadLockSecurityData
ARAUnlockSecurityData
ARAWriteSecurityData
ARAGetUserInfo
ARAGetMySessionRef
ARATickleMe
ARACompleteOperation
Connection Configuration (CCNF Resource ID 200)
A Connection Configuration code resource is executed on the client side when the user selects "Configuration" button on the client in a connection document's security option. It can store 150 bytes of data in a connection document for a line-level security device.
It should display a modal dialog and get any information relevant to connections with line-level security. You can use ARAReadLockSecurityData, ARAReadSecurityData, ARAWriteSecurityData, and ARAUnlockSecurityData to access and modify the security data.
On kSecurityBegin you should get the existing security data. Once you have obtained the data, you should display a dialog box, and allow the user to modify it. When the user is done, you can write the security data if it was modified, using ARAWriteSecurityData.
The following ARA Service Routines can be used by a CCNF code resource:
ARAReadSecurityData
ARAReadLockSecurityData
ARAUnlockSecurityData
ARAWriteSecurityData
ARATickleMe
ARACompleteOperation
Client Side Line-level (CLLN Resource ID 200)
A client-side line-level code resource is executed after a physical connection has been established, using a connection document configured with security. It should communicate with the line-level device, prompting the user for any information the device requires.
A CLLN code resource can use the ARARead and ARAWrite to communicate with the line-level device on the server. The data being read or written is sent over the physical line without any packetization. Your code resource gets control of the line after a connection is established, but before your authentication device allows connection to the ARA server.
On kSecurityBegin you should start the communication process with the server line-level device. You can display a dialog box to obtain information from the user. Once the physical device has authenticated or rejected the user the code resource should call ARAAllowUser or ARADontAllowUser to let ARA transition to the next state.
You can use ARAReadSecurityData to access the 150 bytes of data stored in the connection document. You can not modify this information during authentication. The security data is stored in an alias to a remote server as well as the original connection document, so you can get the data even if the connection is initiated from an alias to a remote server.
A CLLN code resource can use the following ARA Service Routines:
ARARead
ARAWrite
ARAAllowUser
ARADontAllowUser
ARAReadSecurityData
ARATickleMe
ARACompleteOperation
Actions
Actions are one of the parameters passed to your code resource's entry routine. ARA sends them to request a service from your code resource.
All actions are sent during main thread time, so you can allocate memory and make calls to Mac Toolbox routines. The code resource's A5 world is setup prior to calling your routine. The resource fork of your module is open and on top of the resources stack.
You should process actions as quickly as possible. You should not go into loops and use SystemTask calls as a way of returning control back to ARA.
kSecurityStartup
kSecurityStartup is sent immediately after your code resource is loaded. You can allocate any needed memory during the processing of this action, but you should not make any calls to any of the ARA Service Routines. Once processed, you should return kSecurityNoErr. Generally you should use kSecurityBegin to start any processing.
kSecurityShutdown
kSecurityShutdown is the last action sent prior to unloading your code resource. The code resource will not be called any more after this action. You can release any allocated memory. Make sure you have cleaned everything up before returning. You can not use any of the ARA Service Routines during kSecurityShutdown.
kSecurityBegin
kSecurityBegin is sent to request your code resource to perform its operation. E.g. requesting a protocol-level module to authenticate a user. The code resource should start the operation that it is responsible for. You can allocate memory and other needed resources. You can also call ARA Service Routines asynchronously.
kSecurityEnd
kSecurityEnd is sent when the operations that the resource performs are being finished. You should do your cleanup at this time. You can not make any calls to ARA Service Routines after or during this action.
kSecurityDataAvailable
kSecurityDataAvailable is not being used in this release.
kSecurityAbort
kSecurityAbort is sent when the operation of your code resource is being aborted. You should stop any further processing by your code resource (including in your completion routine. E.g. through the use of a flag). Your code resource should terminate any outstanding asynch calls to routines other than ARA Service Routines. Outstanding ARA Service Routines will be aborted by ARA.
kSecurityTickleAction
kSecurityTickleAction is sent to your code resource periodically. You can also request a kSecurityTickleAction explicitly by calling the ARATicleMe routine. When you call ARATickleMe you pass an additional parameter which is sent to your "MySecurityProcEntry" as the LongParam. This additional parameter can be used as a state indicator. E.g. an asynchronous call has finished, so from your completion routine you call ARATickleMe with the state indicator "DidMyAsynchCall" (this can be a value in an enum). In processing of kSecurityTickleAction you check the LongParam to see if it matches "DidMyAsynchCall". If it matches you know you have finished your asynchronous operation and are ready to transition to the next state. You should also do an ARATickleMe when you need to perform main thread time operations (e.g. allocate memory) . When kSecurityTickleAction is being sent periodically by ARA LongParam will be 0. For an example on the use of kSecurityTickleAction and ARATickleMe refer to the Sample module.
ARA Service Routines
ARA Service Routines are a set of functions that code resources have access to. Using these routines, code resources can request ARA services. The following is a list of ARA Service Routines:
ARARead
ARAWrite
ARALogMessage
ARACallBackAt
ARAAllowUser
ARADontAllowUser
ARAReadSecurityData
ARAReadLockSecurityData
ARAWriteSecurityData
ARAUnlockSecurityData
ARAGetUserInfo
ARATickleMe
ARACompleteOperation
The following sub-sections describe each of the routines.
Note
All of the routines expect a MyReference parameter. This value is passed to "MySecurityProcEntry", and is a unique value representing the instance of the security code resource.
This routine is used to issue an asynchronous read call to ARA. The read will complete either when ARA times out, or the number of bytes requested is read. This read is used to read data coming from the remote machine. The protocol-level modules read from each other. The line-level module reads from a device on the server side.
Parameters
MyReference is the unique identifier passed to the code resource's entry routine.
DataPtr points to a location where the data will be read to. It must not be released while the asynchronous read has not completed.
DataSize is the maximum number of bytes to be read to DataPtr. The maximum data size is 500 bytes.
CompletionProc is a function pointer you provide to be called when the read operation has been completed. If a time-out occurs the CompletionProc is called with a kARATimeout result code.
CompletionParam is additional information you can provide which will be passed to the CompletionProc.
Return Value
Result code. Non kARANoErr result codes are usually because the call was not queued.
Note
This is an asynchronous call and can be called during interrupt time. The DataPtr field must not be released until the call has completed.
This routine can be used to write data to the remote machine. For protocol-level authentication the data is transferred over a reliable link, whereas for line-level authentication the data is just transferred over the connection without any packetization. Protocol-level modules write to each other. Line-level modules write to a security device on the server side.
Parameters
MyReference is the unique reference passed to the code resource's entry routine.
DataPtr is a pointer to the data to be written out.
DataSize is the number of bytes to be written. A maximum of 500 bytes can be written.
CompletionProc is a pointer to a completion routine which will be called when the write has been completed.
CompletionParam is additional information you can provide which will be passed to the CompletionProc.
Return Value
Result code. Errors are usually caused when the write call can not be queued.
Note
This is an asynchronous call and can be called at interrupt time. The DataPtr field must not be released until the call has been completed.
This routine can be used to change the phone number which ARA will call back at. In order for this routine to work the call-back must be enabled for the given user. The call-back won't be executed until all other add-on security modules have been executed.
The new number is only used for the current session, and won't change the permanent call-back number.
Parameters
DialString is a Pascal string which contains the phone number to dial. It must be a valid phone number.
CompletionProc is a routine pointer which will be called when the phone number has been assigned (not when the call-back has been made).
CompletionParam can contain additional information you can supply to be passed on to the CompletionProc.
Return Value
Result code.
Note
This is an asynchronous call that can be made at interrupt time.
The CompletionProc is called when the DialString has been stored by ARA. Since another security module could override this DialString by another call to this routine, the user may not get called at this DialString.
This routine can only be used by a server-side protocol-level code resource (SRPR)
This routine is used to let ARA know that the user has been authenticated. It also informs ARA that the operation has been completed. ARA will then send the code resource's entry routine a kSecurityEnd action, after which ARA proceeds to the next state.
Parameters
CompletionProc is a completion routine which will be called when ARA has accepted this call.
CompletionParam is additional information you can supply that will be provided to the CompletionProc.
Return Value
Result code.
Note
This is an asynchronous call that can be made during interrupt time.
You can call this routine when the user has failed authentication. ARA will send a kSecurityEnd action to the code resources entry routine, after which ARA will tear down the connection.
Parameters
Message is an optional Pascal string which states why the user failed authentication. You can pass a NIL for the pointer.
CompletionProc is your routine which will be called when ARA has accepted this call.
CompletionParam is a parameter you can supply which is passed to the CompletionProc.
Return Value
Result code.
Note
This is an asynchronous call that can be made during interrupt time.
This routine is used to read data for the given type of security module which is associated with either a user or a connection. On the server this data is associated with a given user. On the client side this data is associated with the connection. The maximum amount of data that can be stored is 150 bytes.
Parameters
DataPtr points to where the security data is to be read to.
DataSize is the maximum amount of data to read. It should not be larger than 150.
CompletionProc is a pointer to a routine which will be called when the data has been read.
CompletionParam is additional information you can provide to be passed to the CompletionProc
Return Value
Result code.
Note
On the ARA server this data is associated with a given user and stored in the users and groups database. On the client side this data is associated with a given connection.
This routine is used to read and lock data for the given type of security module which is associated with either a user or a connection. On the server this data is associated with a given user. On the client side this data is associated with the connection. The maximum amount of data that can be read or written is 150 bytes. You should use the ARAReadLockSecurityData instead of ARAReadSecurityData if you plan to modify or write the security data. This is crucial on the server, because you can have multiple threads attempting to modify the same data.
Parameters
DataPtr points to where the security data is to be read to.
DataSize is the maximum amount of data to read. It should not be larger than 150.
CompletionProc is a pointer to a routine which will be called when the data has been read.
CompletionParam is additional information you can provide to be passed to the CompletionProc
Return Value
Result code.
Note
On the ARA server this data is associated with a given user and stored in the users and groups database. On the client side this data is associated with a given connection.
You must call ARAUnlockSecurityData to remove the lock from the security data.
This routine can be used by the security modules (mostly configuration code resources) to store configuration data which is associated with either a user or a connection. On the server this data is associated with a user. On the client this data is associated with a connection.
Parameters
DataPtr points to the data to be stored.
DataSize is the number of bytes to store. It should be less than or equal to 150.
CompletionProc is a pointer to a completion routine that will be called when the data has been written.
CompletionParam is additional information you can provide to be passed to the CompletionProc.
Return Value
Result code.
Note
On the ARA server this data is associated with a given user and stored in the users and groups database. On the client side this data is associated with a given connection.
A line-level authentication code resource (CLLN) can not modify the security data.
This routine is used to get information about the user. Currently it returns the user's name. On the server this is the information for the user dialing in, or being configured.
Parameters
DataPtr points to where this information will be stored.
DataSize is the maximum number of bytes to be read.
CompletionProc is a completion routine that will be called when the information has been read.
CompletionParam is additional information you can provide to be passed to the CompletionProc.
This routine causes ARA to send a kSecurityTickleAction to the code resource's entry routine. For example, you can use this routine from completion routines to have your entry routine invoked.
Parameters
TickleParam is additional information you can provide which will be passed to the entry routine in its LongParam parameter. When ARA calls the entry routine with a kSecurityTickleAction it passes a 0 for the LongParam parameter. You can use this as a state indicator.
Return Value
Result code.
Note
This function can be called during interrupt time. The kSecurityTickleAction is sent to the "MySecurityProcEntry" at SystemTask time.
You call this routine when you need to end the operation the code resource is performing. It causes ARA to send a kSecurityEnd action. For example the configuration code resource should call this routine when the user has finished inputting information into its dialog box.
Parameters
MyReference is the unique reference passed to the code resource's entry routine.
// you can remove the unused pragma for any of the parameters you use
#pragma unused(MyReference)
#pragma unused(ResultCode)
#pragma unused(DataPtr)
#pragma unused(DataSize)
#pragma unused(CompletionParam)
// WARNING:
// Do not attempt to allocate or release any memory in this
// routine. Also don't call any Mac Toolbaox/OS routines
// that allocate or release memory. If you need to do this,
// you should call ARATickleMe with a state indicator, and
// allow your DoMyTickle routine to handle it.
return;
}
Appendix C: Miscellaneous
Runtime Environment
ARA builds an A5 world for a code resource, so the module can have its own global data. ARA sets the A5 world automatically, prior to calling any routines (entry, completion) in the code resource.
The module inherits stacks from other executing tasks, and should refrain from recursion and large stack variables.
The resource file from which the code resources are loaded will be on the top of the resource file stack, when ARA executes code resources. The security module's resource file is opened as read-only, and you should not attempt to modify or add any resources.
You must initialize any Toolbox manager's you are using (e.g. InitGraf).
Building an Add-on Security Module
You need MPW 3.2 or later and MPW C to build a security module. The ARA Security Interface disk contains the files you need to build a security interface.
The EmptyShell is a good starting point for putting together a code resource. You can also use the sample module as the starting point for your module. This code can be used in your security modules, but you must keep Apple's copyrights in the source files.
After you have designed your security module (e.g. line-level vs. protocol-level and its working behavior), take the "SecurityShell.c" and code the routines that handle the actions. The Sample Module shows how a protocol-level module that provides a second password is coded.
You must also define the proper 'sinf' resource for your module.
After you have compiled the module you must link it with "SecurityInterface.o". You must also link in "Runtime.o" (included with MPW). SecurityInterface.o must be the first file in the link command. The link command should also have "-m SECURITYINTERFACEENTRYPROC".
For an example of how a security module is build Review the enclosed Sample Module.
ARA Security Interface Disk
The enclosed developer disk contains the interface files and sample modules you can use to build an ARA security module. This sections describes the contents of this disk.
The "Empty Shell" folder contains a file you can use to build a code resource file. It contains place holder routines for processing the ARA actions.
The "Sample Protocol Module" folder contains the complete source for a security module that provides a second password. Using this module, you can assign each user a second password. This is a protocol-level module. You can use this code as a starting point for building your own module.
"Security Interfaces" folder contains the various header files for interfacing with ARA. "SecurityInterface.h", and "SecurityPublic.h" contain all the declarations that your module needs for accessing ARA Service Routines. "SecurityResInfo.h" contains the flags that are used in the 'sinf' resource. "SecurityTypes.r" has the resource declarations for a security module.
"SecurityLibraries" contains "SecurityInterface.o" that must be linked as the first file for each of your code resources.